package com.gzu.finalwork.common.utils;


import com.gzu.finalwork.admin.service.SensitiveOperationLogService;
import com.gzu.finalwork.entity.admin.SensitiveOperationLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 敏感操作AOP切面
 * 用于记录敏感操作日志
 */
@Aspect
@Component
public class SensitiveOperationAspect {

    private static final Logger logger = LoggerFactory.getLogger(SensitiveOperationAspect.class);
    
    @Autowired
    private SensitiveOperationLogService sensitiveOperationLogService;

    /**
     * 定义切点，拦截所有带有@SensitiveOperation注解的方法
     */
    @Pointcut("@annotation(com.gzu.finalwork.common.utils.SensitiveOperation)")
    public void sensitiveOperationPointcut() {
    }

    /**
     * 环绕通知，记录敏感操作日志
     */
    @Around("sensitiveOperationPointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes != null ? attributes.getRequest() : null;
        
        // 获取方法信息
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        SensitiveOperation annotation = method.getAnnotation(SensitiveOperation.class);
        
        LocalDateTime operationTime = LocalDateTime.now();
        
        // 记录操作开始日志
        logger.warn("【敏感操作】{} - {}", annotation != null ? annotation.value() : "未知操作", 
                annotation != null ? annotation.operationType() : "未知类型");
        
        Object result = null;
        
        try {
            // 执行目标方法
            result = point.proceed();
            
            // 记录到数据库
            recordToDatabase(annotation, request, operationTime);
            
        } catch (Exception e) {
            logger.error("【敏感操作异常】{} - 错误信息: {}", 
                    annotation != null ? annotation.value() : "未知操作", e.getMessage(), e);
            
            // 即使异常也要记录到数据库
            recordToDatabase(annotation, request, operationTime);
            
            throw e;
        }
        
        return result;
    }

    /**
     * 记录敏感操作到数据库
     */
    private void recordToDatabase(SensitiveOperation annotation, HttpServletRequest request, LocalDateTime operationTime) {
        try {
            SensitiveOperationLog log = new SensitiveOperationLog();
            
            // 设置基本信息
            if (annotation != null) {
                log.setOperationDesc(annotation.value());
                log.setOperationType(annotation.operationType());
            }
            
            // 获取操作人信息
            if (request != null) {
                Map<String, Object> operatorInfo = UserContextUtil.getOperatorInfo(request);
                if (operatorInfo.get("operatorId") != null) {
                    log.setOperatorId((Long) operatorInfo.get("operatorId"));
                }
                if (operatorInfo.get("operatorUsername") != null) {
                    log.setOperatorUsername((String) operatorInfo.get("operatorUsername"));
                }
            }
            
            // 设置时间信息
            log.setOperationTime(operationTime);
            log.setCreatedAt(LocalDateTime.now());
            
            // 异步记录到数据库
            sensitiveOperationLogService.recordLog(log);
            
        } catch (Exception e) {
            logger.error("记录敏感操作到数据库失败: {}", e.getMessage(), e);
        }
    }
} 